﻿//===========================[ 7 / 25 / 2011 LVI ]=============================
//				Copyright c Vitaly Lyaschenko <SkyChameleon@gmail.com>
//								Source file
// Purpose: 
//=============================================================================
#include "cCreateGeometry.h"

///////////////////////////////////////////////////////////////////////////
// создает сетку указанного размера с заданным шагом
void createGrid( std::vector < vec3 >& vertex, float sizeX, float sizeY, float stride )
{
	float halfsizeX = sizeX / 2;
	float halfsizeY = sizeY / 2;
	
	for ( float x = -halfsizeX; x <= halfsizeX; x += stride ) 
	{
		vertex.push_back( vec3( x, halfsizeY, 0.0f ) );
		vertex.push_back( vec3( x,-halfsizeY, 0.0f ) );
	}

	for ( float y = -halfsizeY; y <= halfsizeY; y += stride )
	{
		vertex.push_back( vec3( halfsizeX, y, 0.0f ) );
		vertex.push_back( vec3(-halfsizeX, y, 0.0f ) );
	}
}
///////////////////////////////////////////////////////////////////////////
// создание координатной сетки ...
void createCoorGrid( std::vector < Vertex_pc >& vertex, float sizeX, float sizeY , float stride, vec3 colorAxis, vec3 colorGrid )
{
	float halfsizeX = sizeX / 2;
	float halfsizeY = sizeY / 2;

	for ( float x = -halfsizeX; x <= halfsizeX; x += stride ) 
	{
		Vertex_pc Vert1, Vert2;
		// если середина сетки -> делаем крупнее оси координат по x
		if ( x == 0 ) 
		{
			Vert1.color( colorAxis ); 
			Vert2.color( colorAxis );

			Vert1.pos( vec3( x - 0.005f, halfsizeY, 0.0f ) );
			Vert2.pos( vec3( x - 0.005f,-halfsizeY, 0.0f ) );
			vertex.push_back( Vert1 );
			vertex.push_back( Vert2 );
			Vert1.pos( vec3( x + 0.005f, halfsizeY, 0.0f ) );
			Vert2.pos( vec3( x + 0.005f,-halfsizeY, 0.0f ) );
			vertex.push_back( Vert1 );
			vertex.push_back( Vert2 );

		} else
		{
			Vert1.color( colorGrid );
			Vert2.color( colorGrid );
		}
		Vert1.pos( vec3( x, halfsizeY, 0.0f ) );
		Vert2.pos( vec3( x,-halfsizeY, 0.0f ) );

		vertex.push_back( Vert1 );
		vertex.push_back( Vert2 );
	}

	for ( float y = -halfsizeY; y <= halfsizeY; y += stride )
	{
		Vertex_pc Vert1, Vert2;
		// если середина сетки -> делаем крупнее оси координат по y
		if ( y == 0 ) 
		{
			Vert1.color( vec3( 0.0f, 0.0f, 0.0f ) );
			Vert2.color( vec3( 0.0f, 0.0f, 0.0f ) );

			Vert1.pos( vec3( halfsizeX, y - 0.005f, 0.0f ) );
			Vert2.pos( vec3(-halfsizeX, y - 0.005f, 0.0f ) );
			vertex.push_back( Vert1 );
			vertex.push_back( Vert2 );
			Vert1.pos( vec3( halfsizeX, y + 0.005f, 0.0f ) );
			Vert2.pos( vec3(-halfsizeX, y + 0.005f, 0.0f ) );
			vertex.push_back( Vert1 );
			vertex.push_back( Vert2 );
		} else
		{
			Vert1.color( vec3( 10.0f, 20.0f, 30.0f ) );
			Vert2.color( vec3( 10.0f, 20.0f, 30.0f ) );
		}
		Vert1.pos( vec3( halfsizeX, y, 0.0f ) );
		Vert2.pos( vec3(-halfsizeX, y, 0.0f ) );

		vertex.push_back( Vert1 );
		vertex.push_back( Vert2 );
	}
}
///////////////////////////////////////////////////////////////////////////
// создание куба
void createCube(std::vector < Vertex_PNT >& vertex,std::vector < _16ubit >& index, float size )
{
	uint numVertices = 24;
	uint numIndices  = 36;

	//float cubeVertices[] =
	//{
	//	-1.0f, -1.0f, -1.0f,
	//	-1.0f, -1.0f, +1.0f,
	//	+1.0f, -1.0f, +1.0f,
	//	+1.0f, -1.0f, -1.0f,
	//	-1.0f, +1.0f, -1.0f,
	//	-1.0f, +1.0f, +1.0f,
	//	+1.0f, +1.0f, +1.0f,
	//	+1.0f, +1.0f, -1.0f,
	//	-1.0f, -1.0f, -1.0f,
	//	-1.0f, +1.0f, -1.0f,
	//	+1.0f, +1.0f, -1.0f,
	//	+1.0f, -1.0f, -1.0f,
	//	-1.0f, -1.0f, +1.0f,
	//	-1.0f, +1.0f, +1.0f,
	//	+1.0f, +1.0f, +1.0f,
	//	+1.0f, -1.0f, +1.0f,
	//	-1.0f, -1.0f, -1.0f,
	//	-1.0f, -1.0f, +1.0f,
	//	-1.0f, +1.0f, +1.0f,
	//	-1.0f, +1.0f, -1.0f,
	//	+1.0f, -1.0f, -1.0f,
	//	+1.0f, -1.0f, +1.0f,
	//	+1.0f, +1.0f, +1.0f,
	//	+1.0f, +1.0f, -1.0f,
	//};
	float cubeVertices[] =
	{
		-size, -size, -size,
		-size, -size, +size,
		+size, -size, +size,
		+size, -size, -size,
		-size, +size, -size,
		-size, +size, +size,
		+size, +size, +size,
		+size, +size, -size,
		-size, -size, -size,
		-size, +size, -size,
		+size, +size, -size,
		+size, -size, -size,
		-size, -size, +size,
		-size, +size, +size,
		+size, +size, +size,
		+size, -size, +size,
		-size, -size, -size,
		-size, -size, +size,
		-size, +size, +size,
		-size, +size, -size,
		+size, -size, -size,
		+size, -size, +size,
		+size, +size, +size,
		+size, +size, -size,
	};

	float cubeNormals[] =
	{
		 0.0f, -1.0f,  0.0f,
		 0.0f, -1.0f,  0.0f,
		 0.0f, -1.0f,  0.0f,
		 0.0f, -1.0f,  0.0f,
		 0.0f, +1.0f,  0.0f,
		 0.0f, +1.0f,  0.0f,
		 0.0f, +1.0f,  0.0f,
		 0.0f, +1.0f,  0.0f,
		 0.0f,  0.0f, -1.0f,
		 0.0f,  0.0f, -1.0f,
		 0.0f,  0.0f, -1.0f,
		 0.0f,  0.0f, -1.0f,
		 0.0f,  0.0f, +1.0f,
		 0.0f,  0.0f, +1.0f,
		 0.0f,  0.0f, +1.0f,
		 0.0f,  0.0f, +1.0f,
		-1.0f,  0.0f,  0.0f,
		-1.0f,  0.0f,  0.0f,
		-1.0f,  0.0f,  0.0f,
		-1.0f,  0.0f,  0.0f,
		+1.0f,  0.0f,  0.0f,
		+1.0f,  0.0f,  0.0f,
		+1.0f,  0.0f,  0.0f,
		+1.0f,  0.0f,  0.0f
	};

	float cubeTexCoor[] =
	{
		0.0f, 0.0f,
		0.0f, 1.0f,
		1.0f, 1.0f,
		1.0f, 0.0f,
		1.0f, 0.0f,
		1.0f, 1.0f,
		0.0f, 1.0f,
		0.0f, 0.0f,
		0.0f, 0.0f,
		0.0f, 1.0f,
		1.0f, 1.0f,
		1.0f, 0.0f,
		0.0f, 0.0f,
		0.0f, 1.0f,
		1.0f, 1.0f,
		1.0f, 0.0f,
		0.0f, 0.0f,
		0.0f, 1.0f,
		1.0f, 1.0f,
		1.0f, 0.0f,
		0.0f, 0.0f,
		0.0f, 1.0f,
		1.0f, 1.0f,
		1.0f, 0.0f,
	};

	_16ubit cubeIndices[] =
	{
		 0,  2,  1,
		 0,  3,  2, 
		 4,  5,  6,
		 4,  6,  7,
		 8,  9, 10,
		 8, 10, 11, 
		12, 15, 14,
		12, 14, 13, 
		16, 17, 18,
		16, 18, 19, 
		20, 23, 22,
		20, 22, 21
	};


	int v = 0, n = 0, t = 0;
	// для каждой вершины куба
	for ( int face = 0; face != numVertices; face++ )
	{
		Vertex_PNT _vert;

		memcpy( &_vert,    cubeVertices + v, sizeof(float) * 3 );
		v += 3;
		memcpy( &_vert.nx, cubeNormals  + n, sizeof(float) * 3 );
		n += 3;
		memcpy( &_vert.u,  cubeTexCoor  + t, sizeof(float) * 2 );
		t += 2;

		vertex.push_back(_vert);
	}

	index.resize(numIndices);
	memcpy(index.data(),cubeIndices,sizeof(_16ubit)*36 );
}

// http://www.gamedev.ru/code/forum/?id=147171#m4
bool createCylinder ( float diameter, float length, size_t facet, 
	std::vector < vec3 >& vertex, std::vector < _16ubit >& index, float& volume ) 
{
	vertex.reserve ( facet * 2 );
	index.reserve ( facet * 12 );

	//радиус
	const float R = diameter / 2.0f;

	//половина длины
	const float L = length / 2.0f;

	const float AndleStep = degreesToRadians( 360.0f / facet ) ;

	//первая боковая поверхность
	float Step = 0.0f ;
	for ( size_t i = 0 ; i != facet ; ++ i )
	{  
		vertex.push_back ( vec3 ( L , R * cos ( Step ) , R * sin ( Step ) ) ) ;    
		Step += AndleStep ;
	}
	for ( size_t i = 0; i != facet - 2; ++ i )
	{
		index.push_back ( 0 ) ;
		index.push_back ( i + 1 );
		index.push_back ( i + 2 );
	}
	//вторая боковая поверхность
	Step = 0.0f ;
	for ( size_t i = 0; i != facet; ++ i )
	{  
		vertex.push_back ( vec3 ( - L , R * cos ( Step ) , R * sin ( Step ) ) ) ;    
		Step += AndleStep ;
	}
	for ( size_t i = 0; i != facet - 2; ++ i )
	{
		index.push_back ( i + facet + 2 );
		index.push_back ( i + facet + 1 );
		index.push_back ( facet ) ;
	}
	//поверхность
	for ( size_t i = 0 ; i != facet ; ++ i )
	{
		size_t Index = i + facet + 1;

		if ( Index == facet * 2 )
			Index = facet ;

		index.push_back ( i ) ;
		index.push_back ( i + facet );
		index.push_back ( Index );

		index.push_back ( i );
		index.push_back ( Index ) ;
		index.push_back ( ( i + 1 ) % facet );
	}

	//расчёт объёма
	const float Footprint = ( facet / 2.0f ) * R * R * sin ( 2.0f * PI / facet );
	volume = Footprint * length;

	return true;
}